package onlinebanking.client;

import java.util.GregorianCalendar;

import javax.swing.JOptionPane;

import onlinebanking.client.gui.ClientPanel;
import onlinebanking.client.gui.ConfirmTransactionDetailsPanel;
import onlinebanking.constants.MSG;
import onlinebanking.network.Message;
import onlinebanking.network.NetworkSwitch;
import onlinebanking.network.SimpleNetworkSwitch;

/**
 * The class that receives and interprets the messages from the server.
 * 
 * @author Edgar
 * 
 */
public class ServerListener extends Thread {
	SimpleClient mysimpleclient;
	NetworkSwitch networkSwitch;
	ClientPanel parent;

	/**
	 * Creates a new instance of the <code>ServerListener</code>. 
	 * @param mysimpleclient The parent client.
	 * @param networkSwitch The channel from the client to the network.
	 */
	ServerListener(SimpleClient mysimpleclient, NetworkSwitch networkSwitch) {
		this.mysimpleclient = mysimpleclient;
		this.networkSwitch = networkSwitch;
	}

	/**
	 * Sets the client associated to the server listener.
	 */
	public void setClientPanel(ClientPanel cp) {
		parent = cp;
	}

	@Override
	public void run() {

		while (true) {
			try {
				//TODO decrypt message string
				String messageString = this.networkSwitch.receive();				
				Message messageReceived = new Message(messageString);
				
				
				interpretIncomingMsg(messageReceived);
			} catch (Exception e) {
				// Do something here like alert the user
				System.err.println("Error in connection " + e);
				//e.printStackTrace();
				break;
			}
		}

	}

	// end of run

	/**
	 * Interprets a received message.
	 */
	public void interpretIncomingMsg(Message msg) {
		int messagetype = msg.getMsgType();
		int subtype;
		boolean success;

		//TODO change to hashmap - make some separate functions
		switch (messagetype) {
		case MSG.LOGIN_SUCCESS:
			System.out.println("Login Successful.");
			parent.enableButtons();
			parent.showLoginPanel(false);
			parent.defaultModule();
			break;

		case MSG.LOGIN_FAILED:
			parent.setUsername("");
			JOptionPane.showMessageDialog(null,
					"Login Failed. " + msg.getString("reason"));
			System.out.println("Login Failed. " + msg.getString("reason"));
			
			break;

		case MSG.LOGOUT_SUCCESS:
			System.out.println("Logout Successful.");
			parent.disableButtons();
			parent.showLoginPanel(true);
			parent.setUsername("Logout successful.");
			break;

		case MSG.USER_NOT_LOGGED_IN:
			System.out.println("Not logged in.");
			break;
		
		case MSG.ANNOUNCEMENTS:
			System.out.println("Announcement received.");
			parent.announcementsPanel.clearAnnouncements();
			String announcements = "<html>";
			int msgcount = msg.getInt("count");
			for(int i = msgcount; i>=0; i-- ){
				announcements += "<p>" +msg.getString("#"+i)+ "</p><br>";
			}
			announcements += "</html>";
			
			parent.announcementsPanel.appendAnnouncement(announcements);
			break;
		
		case MSG.MY_BANK_ACCOUNTS:

			subtype = msg.getMsgSubType();

			switch (subtype) {
			case MSG.LIST_OF_BANKACCOUNTS:
				System.out.println("My bankaccounts:");
				int noOfAccounts = msg.getInt("count");
				if(noOfAccounts > 0){
					parent.logoutPanel.clearBankAccountDropDown();
				}
				for (int i = 1; i <= noOfAccounts; i++) {
					String accountno = msg.getString("#" + i);
					parent.logoutPanel.addBankAccountToDropDown(accountno);
					
					System.out.println(i + ") Account no:"
							+ msg.getString("#" + i));
				}
				break;

			case MSG.SELECT_ACTIVE_ACCOUNT:
				success = msg.getSuccess();
				System.out.println(success ? "Account selected"
						: "Account selection failed. Try again.");
				
				JOptionPane.showMessageDialog(null, success ? "Account selected"
						: "Account selection failed. Try again.");
				
				break;
			}

			break;

		case MSG.BALANCE_RESPONSE:
			success = msg.getSuccess();
			if (success) {
				double balance = msg.getDouble("balance");
				String accountno = msg.getString("accountno");
				System.out.println("Remaining Balance:" + balance);
				parent.accountBalancePanel
						.setDisplayAccount("Balance for account# " + accountno);
				parent.accountBalancePanel
						.setDisplayBalance(" Remaining Balance: " + balance);
			} else {
				System.out.println("Error:" + msg.getString("reason"));
			}
			break;

		case MSG.INIT_FUNDSTRANSFER:
			success = msg.getSuccess();
			System.out.println("INIT FUNDSTRANSFER SUCCESS:" + success
					+ " reason:" + msg.getString("reason"));
			// do something if successful or not
			if(success){
				JOptionPane.showMessageDialog(null, "Transaction succesfully initalized");
			}else{
				JOptionPane.showMessageDialog(null, "Transaction initalization failed. "+ msg.getString("reason"));
			}
			break;

		case MSG.CONFIRM_TRANSACTION:
			boolean success2 = msg.getSuccess();
			System.out.println("Trans Confirmation SUCCESS:" + success2
					+ " reason:" + msg.getString("reason"));
			String prompt = ((success2)? "Transaction confirmed" : "Error in confirming transaction. Please try again." + msg.getString("reason"));
			JOptionPane.showMessageDialog(null, prompt);
			break;

		case MSG.VIEW_TRANSACTIONS:
			int transactioncount = msg.getInt("transactioncount");
			subtype = msg.getMsgSubType();

			switch (subtype) {
			case MSG.LIST_OF_PENDING_TRANSACTIONS:
				
				
				
				// each iteration of the loop pertains to a single pending
				// transaction
				for (int transNo = 0; transNo < transactioncount; transNo++) {
					// print these variables to GUI

					int transactionid = msg.getInt("transaction" + transNo
							+ "transactionid");
					int bankaccountno = msg.getInt("transaction" + transNo
							+ "bankaccountno");
					String transactiontype = msg.getString("transaction"
							+ transNo + "transactiontype");
					int ammount = msg.getInt("transaction" + transNo
							+ "ammount");
					String initiatedby = msg.getString("transaction" + transNo
							+ "initiatedby");
					int expDay = msg.getInt("transaction" + transNo
							+ "expiryDay");
					int expMonth = msg.getInt("transaction" + transNo
							+ "expiryMonth");
					int expYear = msg.getInt("transaction" + transNo
							+ "expiryYear");

					System.out.println(transNo + ") Transaction : "
							+ transactionid + "\t" + bankaccountno + "\t"
							+ transactiontype + "\t" + ammount + "\t"
							+ initiatedby + "\t" + expDay + "-" + expMonth
							+ "-" + expYear);
					String expirationdate = expDay + "-" + expMonth + "-" + expYear;
					
					parent.confirmTransactionPanel.addRow(transactionid+"", bankaccountno+"", transactiontype, ammount+"", initiatedby, expirationdate);
				}

				System.out.println(transactioncount + " transactions found");

				break;// end of LIST_OF_PENDING
			
			case MSG.DETAIL_SPECIFIC_TRANSACTION:
				System.out.println("Details here...");
				
				ConfirmTransactionDetailsPanel ctdp = this.parent.ConfirmTransactionDetailsPanel;
				
				ctdp.TransactionTypeData.setText(msg.getString("transactiontype"));
				ctdp.TransactionStatusData.setText(msg.getString("transactionstatus"));
				ctdp.TransactionOwnerData.setText(msg.getString("transactionowner"));
				
				ctdp.AmountData.setText(msg.getDouble("ammounttransfer")+"");
				ctdp.SourceAccountData.setText(msg.getInt("srcaccount")+"");
				ctdp.DestinationAccountData.setText(msg.getInt("destaccount")+"");
				
				String expiryStr = getMonthShortString(msg.getInt("expMonth"))+" "+ msg.getInt("expDay") + ",  " + msg.getInt("expYear");
				
				
				ctdp.ExpirationData.setText(expiryStr);
				ctdp.ProcessedOnData.setText("");
				
				
				
			default:
				break;
			}

			break;// END OF VIEW_TRANSACTIONS

		// case MSG.LOGIN_SUCCESS:
		// System.out.println("Login Successful.");
		// break;

		default:
			System.out.println("UNKOWN RESPONSE:" + msg.getMsgType());
			break;
		}
	}
	
	
	public static String getMonthString(int monthno){
		monthno++;
		switch (monthno) {
		case 1:
			return "January";
		case 2:
			return "February";
		case 3:
			return "March";
		case 4:
			return "April";
		case 5:
			return "May";
		case 6:
			return "June";
		case 7:
			return "July";
		case 8:
			return "August";
		case 9:
			return "September";
		case 10:
			return "October";
		case 11:
			return "November";
		case 12:
			return "December";

		default:
			return "---";
		}
	}
	
	public static String getMonthShortString(int monthno){
		return getMonthString(monthno).substring(0, 3);
	}
}
